home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Original Shareware 1.1
/
The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso
/
32
/
advsys.zip
/
ADVCOM.C
< prev
next >
Wrap
Text File
|
1987-06-28
|
15KB
|
635 lines
/* advcom.c - a compiler for adventure games */
/*
Copyright (c) 1986, by David Michael Betz
All rights reserved
*/
#include "advcom.h"
#include "advavl.h"
#include "advdbs.h"
#define BANNER \
"ADVCOM v1.2a - Copyright (c) 1987, by David Betz"
/* symbol tables */
SYMBOL *symbols;
ARGUMENT *arguments;
ARGUMENT *temporaries;
/* adventure id information */
char aname[19];
int aversion;
/* word table */
int wtable[WMAX+1],wcnt;
/* object table */
int otable[OMAX+1],ocnt;
/* action table */
int atable[AMAX+1],acnt;
/* constant, variable and property symbol counts */
int ccnt,vcnt,pcnt;
/* data and code space */
char *data,*code;
int dptr,cptr;
/* buffer for building an object */
int objbuf[OSIZE];
int nprops;
/* global variables */
char ifile[FMAX]; /* input file name */
char ofile[FMAX]; /* output file name */
FILE *ifp; /* input file pointer */
unsigned int msgoff; /* message section offset */
TREE *words; /* word tree */
int curwrd; /* current word number */
int curobj; /* current object */
int curact; /* current action */
int def_flag; /* default action flag value */
int def_mask; /* default action mask value */
/* header information variables */
int h_init; /* initialization code */
int h_update; /* update code */
int h_before; /* before handler code */
int h_after; /* after handler code */
int h_error; /* error handling code */
/* external routines */
extern char *malloc();
extern char *calloc();
extern TREE *tnew();
/* external variables */
extern int errcount; /* error count */
extern int t_value; /* token value */
extern char t_token[]; /* token string */
extern char *t_names[]; /* token names */
extern long ad_foff; /* data file offset */
/* forward declarations */
SYMBOL *sfind();
SYMBOL *senter();
char *save();
/* main - the main routine */
main(argc,argv)
int argc; char *argv[];
{
int tkn,obj,i;
/* initialize */
advinit(BANNER,argc,argv,ifile,ofile);
wcnt = ocnt = acnt = ccnt = vcnt = pcnt = msgoff = 0;
symbols = NULL; arguments = temporaries = NULL;
h_init = h_update = h_before = h_after = h_error = NIL;
def_flag = def_mask = 0;
aname[0] = 0;
sinit();
/* setup the code and data space */
if ((data = calloc(1,DMAX)) == 0)
advfatal("insufficient memory");
if ((code = calloc(1,CMAX)) == 0)
advfatal("insufficient memory");
dptr = cptr = 1; /* make sure nothing has a zero offset */
/* open the input file */
if ((ifp = fopen(ifile,"r")) == NULL)
advfatal("can't open input file");
/* create and initialize the output file */
ad_create(ofile);
for (i = 0; i++ < 512; ad_putc('\0'))
;
/* create the word tree */
words = tnew();
/* enter builtin constants */
center("t",-1);
center("nil",0);
/* enter the builtin variables */
venter("$actor");
venter("$action");
venter("$dobject");
venter("$ndobjects");
venter("$iobject");
venter("$ocount");
/* enter the preposition "to" */
add_word("to",WT_PREPOSITION);
/* process statements until end of file */
while ((tkn = token()) == T_OPEN) {
frequire(T_IDENTIFIER);
/* identification statement */
if (match("adventure"))
do_adventure();
/* vocabulary statements */
else if (match("adjective"))
do_word(WT_ADJECTIVE);
else if (match("preposition"))
do_word(WT_PREPOSITION);
else if (match("conjunction"))
do_word(WT_CONJUNCTION);
else if (match("article"))
do_word(WT_ARTICLE);
else if (match("synonym"))
do_synonym();
/* constant, variable, function and default definition statements */
else if (match("define"))
do_define();
else if (match("variable"))
do_variable();
else if (match("default"))
do_default();
/* property definition statement */
else if (match("property"))
do_defproperty();
/* handle the init, before and after code statements */
else if (match("init"))
h_init = do_code(t_token);
else if (match("update"))
h_update = do_code(t_token);
else if (match("before"))
h_before = do_code(t_token);
else if (match("after"))
h_after = do_code(t_token);
else if (match("error"))
h_error = do_code(t_token);
/* action definition statement */
else if (match("action"))
do_action();
/* object definition statements */
else if (match("object"))
do_object(t_token,NIL);
/* object instance definition statements */
else if (obj = ofind(t_token))
do_object(t_token,obj);
/* error, unknown statement */
else
error("Unknown statement type");
}
require(tkn,T_EOF);
/* close the input file */
fclose(ifp);
/* output the data structures */
output();
/* close the output file */
ad_close();
}
/* getvalue - get a value */
int getvalue()
{
SYMBOL *sym;
switch (token()) {
case T_IDENTIFIER: if (sym = sfind(t_token))
return (sym->s_value);
return (oenter(t_token));
case T_NUMBER: return (t_value);
case T_STRING: return (t_value);
default: error("Expecting identifier, number or string");
return (0);
}
}
/* dalloc - allocate data space */
int dalloc(size)
int size;
{
if ((dptr += size) > DMAX)
advfatal("out of data space");
return (dptr - size);
}
/* add_word - add a word to the dictionary */
int add_word(str,type)
char *str; int type;
{
if ((curwrd = tfind(words,str)) == NIL) {
if (wcnt < WMAX) {
curwrd = ++wcnt;
wtable[curwrd] = type;
tenter(words,str);
}
else {
error("too many words");
curwrd = 0;
}
}
else if (wtable[curwrd] == WT_UNKNOWN)
wtable[curwrd] = type;
else if (type != WT_UNKNOWN && type != wtable[curwrd])
error("Ambiguous word type");
return (curwrd);
}
/* add_synonym - add a synonym to a word */
int add_synonym(str,wrd)
char *str; int wrd;
{
curwrd = wrd;
return (tenter(words,str));
}
/* getword - get a word from an object field */
int getword(off)
int off;
{
return ((data[off] & 0xFF) | (data[off+1] << 8));
}
/* putword - put a word into an object field */
putword(off,dat)
int off,dat;
{
data[off] = dat;
data[off+1] = dat >> 8;
}
/* getbyte - get a byte from an object field */
int getbyte(off)
int off;
{
return (data[off]);
}
/* putbyte - put a byte into an object field */
putbyte(off,dat)
int off,dat;
{
data[off] = dat;
}
/* output - output the binary data structures */
output()
{
int woff,wsize; /* word table offset and size */
int ooff,osize; /* object table offset and size */
int aoff,asize; /* action table offset and size */
int toff,tsize; /* word type table offset and size */
int voff,vsize; /* variable table offset and size */
int soff,ssize; /* save area offset and size */
int dsize; /* data size without dictionary */
int dbase,cbase,size,mblk,dblk,i;
/* make sure the adventure id information is present */
if (aname[0] == 0) {
xerror("no adventure identification information");
strcpy(aname,"ADVENTURE");
aversion = 0;
}
/* pad the remainder of this message block */
while (msgoff & 0x007F)
{ ad_putc('\0'); ad_putc('\0'); ad_putc('\0'); ad_putc('\0'); msgoff++; }
/* save the size of the data area before the dictionary */
dsize = dptr;
/* insert the vocabulary into the data array */
woutput(words->tr_root);
/* compute table offsets */
woff = 0; wsize = tentries(words) * 2 + 2;
toff = woff + wsize; tsize = wcnt;
ooff = toff + tsize; osize = ocnt * 2 + 2;
aoff = ooff + osize; asize = acnt * 2 + 2;
voff = aoff + asize; vsize = vcnt * 2 + 2;
dbase = voff + vsize;
cbase = dbase + dptr;
/* compute the resident structure size */
size = wsize+tsize+osize+asize+vsize+dptr+cptr;
/* set the save area parameters */
soff = voff; ssize = vsize + dsize;
/* compute the first block for message text */
mblk = 1;
dblk = (int)(ad_foff >> 9);
/* output the word table */
word_out(tentries(words));
wtoutput(words->tr_root);
/* output the word type table */
for (i = 1; i <= wcnt; i++)
byte_out(wtable[i]);
/* output the object table */
word_out(ocnt);
for (i = 1; i <= ocnt; i++) {
if (otable[i] == NIL)
undef_object(i);
word_out(otable[i]);
}
/* output the action table */
word_out(acnt);
for (i = 1; i <= acnt; i++)
word_out(atable[i]);
/* beginning of saveable data */
/* output the variable table */
word_out(vcnt);
for (i = 1; i <= vcnt; i++)
word_out(NIL);
/* output the data space */
for (i = 0; i < dptr; )
byte_out(data[i++]);
/* end of saveable data */
/* output the code space */
for (i = 0; i < cptr; )
byte_out(code[i++]);
/* output the file header */
ad_seek(0L);
word_out(size); /* resident structure size */
str_out("ADVSYS",6);/* magic information */
word_out(VERSION); /* data structure version number */
str_out(aname,18); /* adventure name */
word_out(aversion); /* adventure version number */
word_out(woff); /* word table offset */
word_out(toff); /* word type table offset */
word_out(ooff); /* object table offset */
word_out(aoff); /* action table offset */
word_out(voff); /* variable table offset */
word_out(dbase); /* base of data */
word_out(cbase); /* base of code */
word_out(dblk); /* first data block */
word_out(mblk); /* first message text block */
word_out(h_init); /* initialization code */
word_out(h_update); /* update code */
word_out(h_before); /* before handler code */
word_out(h_after); /* after handler code */
word_out(h_error); /* error handling code */
word_out(soff); /* save area offset */
word_out(ssize); /* save area size */
/* show statistics */
printf("[ words: %d ]\n",tentries(words));
printf("[ word types: %d ]\n",wcnt);
printf("[ objects: %d ]\n",ocnt);
printf("[ actions: %d ]\n",acnt);
printf("[ variables: %d ]\n",vcnt);
printf("[ data: %d ]\n",dsize);
printf("[ code: %d ]\n",cptr);
printf("[ dictionary: %d ]\n",dptr-dsize);
printf("[ text: %ld ]\n",(long) msgoff * 4L);
printf("[ save area: %d ]\n",ssize);
printf("[ errors: %d ]\n",errcount);
advpause();
}
/* woutput - output the word data */
woutput(node)
TNODE *node;
{
int wnum,wrd;
if (node) {
woutput(LLINK(node));
wnum = WORD(node);
wrd = WORD(node) = dalloc(strlen(KEY(node))+3);
putword(wrd,wnum);
strcpy(data+wrd+2,KEY(node));
if (wtable[wnum] == WT_UNKNOWN)
printf("Type of word %s is unknown\n",KEY(node));
woutput(RLINK(node));
}
}
/* wtoutput - output the word table */
wtoutput(node)
TNODE *node;
{
if (node) {
wtoutput(LLINK(node));
word_out(WORD(node));
wtoutput(RLINK(node));
}
}
/* undef_object - complain about an undefined object */
undef_object(n)
int n;
{
char msg[100];
SYMBOL *sym;
for (sym = symbols; sym != NULL; sym = sym->s_next)
if (sym->s_type == ST_OBJECT && n == sym->s_value) {
sprintf(msg,"Object %s is undefined",sym->s_name);
xerror(msg);
break;
}
}
/* str_out - output a string */
str_out(str,len)
char *str; int len;
{
while (len--)
byte_out(*str++);
}
/* word_out - output a word */
word_out(dat)
int dat;
{
byte_out(dat);
byte_out(dat >> 8);
}
/* byte_out - output a byte */
byte_out(dat)
int dat;
{
ad_putc((~dat - 30) & 0xFF);
}
/* oenter - enter an object into the symbol table */
int oenter(name)
char *name;
{
SYMBOL *sym;
if (sym = sfind(name)) {
if (sym->s_type != ST_OBJECT)
error("Not an object");
return (sym->s_value);
}
if (ocnt < OMAX) {
senter(name,ST_OBJECT,++ocnt);
otable[ocnt] = NIL;
}
else
error("too many objects");
return (ocnt);
}
/* ofind - find an object in the symbol table */
int ofind(name)
char *name;
{
SYMBOL *sym;
if (sym = sfind(name)) {
if (sym->s_type != ST_OBJECT)
return (NIL);
return (sym->s_value);
}
return (NIL);
}
/* aenter - enter an action into the symbol table */
int aenter(name)
char *name;
{
SYMBOL *sym;
if (sym = sfind(name)) {
if (sym->s_type != ST_ACTION)
error("Not an action");
return (sym->s_value);
}
if (acnt < AMAX) {
senter(name,ST_ACTION,++acnt);
atable[acnt] = NIL;
}
else
error("too many actions");
return (acnt);
}
/* venter - enter a variable into the symbol table */
int venter(name)
char *name;
{
SYMBOL *sym;
if (sym = sfind(name)) {
if (sym->s_type != ST_VARIABLE)
error("Not a variable");
return (sym->s_value);
}
senter(name,ST_VARIABLE,++vcnt);
return (vcnt);
}
/* penter - enter a property into the symbol table */
int penter(name)
char *name;
{
SYMBOL *sym;
if (sym = sfind(name)) {
if (sym->s_type != ST_PROPERTY)
error("Not a property");
return (sym->s_value);
}
senter(name,ST_PROPERTY,++pcnt);
return (pcnt);
}
/* center - enter a constant into the symbol table */
center(name,value)
char *name; int value;
{
if (sfind(name)) {
error("Already defined");
return;
}
senter(name,ST_CONSTANT,value);
}
/* sfind - find a symbol in the symbol table */
SYMBOL *sfind(name)
char *name;
{
SYMBOL *sym;
for (sym = symbols; sym != NULL; sym = sym->s_next)
if (strcmp(name,sym->s_name) == 0)
break;
return (sym);
}
/* senter - enter a symbol into the symbol table */
SYMBOL *senter(name,type,value)
char *name; int type,value;
{
SYMBOL *sym;
if ((sym = (SYMBOL *)malloc(sizeof(SYMBOL))) == NULL)
advfatal("out of memory");
sym->s_name = save(name);
sym->s_type = type;
sym->s_value = value;
sym->s_next = symbols;
symbols = sym;
return (sym);
}
/* frequire - fetch a token and check it */
frequire(rtkn)
int rtkn;
{
require(token(),rtkn);
}
/* require - check for a required token */
require(tkn,rtkn)
int tkn,rtkn;
{
char msg[100];
if (tkn != rtkn) {
sprintf(msg,"Expecting %s",t_names[rtkn]);
error(msg);
}
}
/* save - allocate memory for a string */
char *save(str)
char *str;
{
char *new;
if ((new = malloc(strlen(str)+1)) == NULL)
advfatal("out of memory");
strcpy(new,str);
return (new);
}
/* match - compare a string with the current token */
int match(str)
char *str;
{
return (strcmp(str,t_token) == 0);
}